pub fn convert_base(num_str: &str, to_base: u32) -> String {
    let lbracket = num_str.find('(').unwrap();
    let rbracket = num_str.find(')').unwrap();
    let raw_num_str = &num_str[..lbracket];
    let base_num = num_str[(lbracket + 1)..rbracket].parse::<u32>().unwrap();

    let mut raw_num = 0;
    for ch in raw_num_str.chars() {
        let num = match ch {
            '0'..='9' => ch as u8 - b'0',
            'a'..='z' => ch as u8 - b'a',
            'A'..='Z' => ch as u8 - b'A',
            _ => unreachable!(),
        };
        raw_num = raw_num * base_num + (num as u32);
    }
    let mut res = Vec::new();
    while raw_num > 0 {
        let ch = match raw_num % to_base {
            m @ 0..=9 => b'0' + (m as u8),
            m @ 10..=15 => b'a' + ((m - 10) as u8),
            _ => unreachable!(),
        };
        res.push(ch);
        raw_num /= to_base;
    }
    res.reverse();
    String::from_utf8(res).unwrap()
}
